package top.jacktgq.cas.account.v2;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicReference;
public class TestAccount {
	public static void main(String[] args) {
		DecimalAccount.demo(new DecimalAccountCas(new BigDecimal("10000")));
	}
}
class DecimalAccountCas implements DecimalAccount {
	private AtomicReference<BigDecimal> balance;
	
	public DecimalAccountCas(BigDecimal balance) {
		this.balance = new AtomicReference<BigDecimal>(balance);
	}

	@Override
	public BigDecimal getBalance() {
		return balance.get();
	}

	@Override
	public void withdraw(BigDecimal amount) {
		while(true) {
			BigDecimal prev = balance.get();
			BigDecimal next = prev.subtract(amount);
			if(balance.compareAndSet(prev, next)) {
				break;
			}
		}
	}

}

interface DecimalAccount {
	//获取余额
	BigDecimal getBalance();
	
	//取款
	void withdraw(BigDecimal amount);
	
	/**
	 * 方法内会启动1000个线程，每个线程做-10元的操作，
	 * 如果初始余额为10000元，那么正确的结果应当是0
	 */
	static void demo(DecimalAccount account) {
		List<Thread> threadList = new ArrayList<Thread>();
		for(int i = 0; i < 1000; i++) {
			threadList.add(new Thread(() -> {
				account.withdraw(BigDecimal.TEN);
			}));
		}
		
		long start = System.currentTimeMillis();
		
		threadList.forEach(Thread :: start);
		threadList.forEach(t -> {
			try {
				t.join();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		});
		long end = System.currentTimeMillis();
		System.out.println("balance:" + account.getBalance() + ",cost:" + (end - start) + " ms");
		
	}
}